
// 专门绘制存档文件标签，一横一竖


import path from "path";
import fs from "fs";
import { jsPDF, TextOptionsLight } from "jspdf";
import "./heiti-normal.js";
import XLSX from "xlsx";
import { parse } from 'smol-toml'

interface Point {
  x: number;
  y: number;
}

interface Rect {
  w: number;
  h: number;
}

type Gap = Point;

interface Profile {
  name: string
  paper_size: Rect
  label_size: Rect
  gap: Gap
  zero_point: Point
}



const INPUT_PROFILE = process.argv[2];
const INPUT_FILE = process.argv[3]

// 主函数

async function main() {
  usage()

  const config: any = readTomlConfig('config.toml')

  const profile = config[INPUT_PROFILE] as Profile
  showProfile(profile);

  // 打单独的标签就不需要读取xlsx文件了，直接写内容
  const contents = readXlsx(INPUT_FILE);
  // const contents = [
  //   [ '序号', '标题', '文号', '发文机关', '日期', '标签', '备注' ],
  //   [ '', '玉溪市2024年粗钢产量调控材料', '', '', '2024/7/19', '', '' ]
  // ]
  console.log("Contents", contents);

  drawLabels(profile, contents, "res.pdf", true);
  console.log("Done");


}

main();

/**
 * 绘制单张存档文件单子
 * @param profile 配置
 * @param content 内容
 */
function drawDocLabel(pdf: jsPDF, content: string[], point: Point, withBorder: boolean) {

  const hProfile: Rect = {
    w: 88,
    h: 55
  }

  const vProfile: Rect = {
    w: 38,
    h: 180
  }

  const radius = 0
  const { x, y } = point;

  const vPoint = {
    x: x + 100,
    y: y
  }

  const { x: vx, y: vy } = vPoint

  if (withBorder) {

    pdf.text('沿红线剪下来', 10, 10)

    pdf.setLineWidth(0.1);
    pdf.setDrawColor("#FF0000");
    // 画横框

    pdf.roundedRect(x, y, hProfile.w, hProfile.h, radius, radius).fill();

    // 画竖框
    pdf.roundedRect(vx, vy, vProfile.w, vProfile.h, radius, radius).fill();

    pdf.setLineWidth(1);
    pdf.setDrawColor("#0000FF");

    // 画横框

    pdf.roundedRect(x + 2, y + 2, hProfile.w - 4, hProfile.h - 4, 2, 2).fill();

    // 画竖框
    pdf.roundedRect(vx + 2, vy + 2, vProfile.w - 4, vProfile.h - 4, 2, 2).fill();

  }

  // 
  // pdf.circle(x, y, 1)

  // 写横版内容

  drawText(pdf, point, hProfile.w / 2, 10, '存档文件', 14, 'center', 88)
  drawText(pdf, point, hProfile.w / 2, 25, content[1], 16, 'center', 80)
  drawText(pdf, point, hProfile.w / 2, 45, content[2], 14, 'center', 88)


  // 左下角，标签
  drawText(pdf, point, 5, 50, '产业发展科', 12, 'left', 40)

  // 右下角，日期
  drawText(pdf, point, 83, 50, content[4], 12, 'right', 40)


  // 写竖版内容
  // 正中间上方 产业发展科
  drawText(pdf, vPoint, vProfile.w / 2, 10, '存档文件', 14, 'center', 32)



  drawText(pdf, vPoint, vProfile.w / 2, 30, content[1], 16, 'center', 32)
  drawText(pdf, vPoint, vProfile.w / 2, 130, content[2], 14, 'center', 32)

  // 下方，日期
  drawText(pdf, vPoint, vProfile.w / 2, 160, '产业发展科', 12, 'center', 32)
  drawText(pdf, vPoint, vProfile.w / 2, 170, content[4], 12, 'center', 32)

  return pdf;

}

function usage() {
  console.log(`
npm run dev <profile> <xlsx_file>
    `)
}
function readTomlConfig(filePath: string): object {
  const content = fs.readFileSync(filePath, 'utf8')
  return parse(content)
}

function readXlsx(filePath: string): string[][] {
  const wb = XLSX.readFile(filePath);
  const ws = wb.Sheets[wb.SheetNames[0]];
  return XLSX.utils.sheet_to_json(ws, { header: 1, defval: '' });
}

function drawLabels(
  profile: Profile,
  contents: string[][],
  filePath: string,
  withBorder: boolean = false,
) {
  const { paper_size } = profile

  const orientation = paper_size.w > paper_size.h ? "landscape" : "portrait";
  const pdf = new jsPDF({
    orientation: orientation, // 方向要根据纸张尺寸设置，这里是横向
    unit: "mm",
    format: [paper_size.w, paper_size.h],
  });

  pdf.setFont("heiti");


  const head = contents.shift() ?? [];
  for (let i = 0; i < contents.length; i++) {

    const labelContents = contents[i].map(
      // (v: any, j: number) => `${head[j]}： ${v}`,
      (v: any, j: number) => v,
    );
    const point = {
      x: 20,
      y: 20
    }

    drawDocLabel(pdf, labelContents, point, withBorder);
    pdf.addPage();
  }

  console.log(`共生成 ${contents.length} 页标签`);

  // 保存PDF文档
  pdf.save(tryFilePath(filePath));
}



/**
 * 计算纸张上最大行数列数
 * @param paper 纸张尺寸
 * @param label 标签尺寸
 * @param gap 间隔尺寸
 * @returns 行数列数
 */
function calcMaxRowCol(
  paper: Rect,
  label: Rect,
  gap: Gap,
  zeroPoint: Point,
): { row: number; col: number } {
  const maxCol = Math.floor(
    (paper.w - zeroPoint.x + gap.x) / (label.w + gap.x),
  );
  const maxRow = Math.floor(
    (paper.h - zeroPoint.y + gap.y) / (label.h + gap.y),
  );
  return { row: maxRow, col: maxCol };
}

/**
 * 展示配置
 * @param paper 纸张尺寸
 * @param label 标签尺寸
 * @param gap 间隔尺寸
 * @param zeroPoint 原点位置
 */
function showProfile(profile: Profile) {
  const { paper_size, label_size, gap, zero_point } = profile
  const { row, col } = calcMaxRowCol(paper_size, label_size, gap, zero_point);
  console.log(`参数（mm）：
纸张宽高：${paper_size.w}, ${paper_size.h}
标签宽高：${label_size.w}, ${label_size.h}
标签间隔：${gap.x}, ${gap.y}
标签原点：${zero_point.x}, ${zero_point.y}
一张纸上标签行列：${row} 行 ${col} 列
一张纸上标签数量：${row * col} 张
`);
}


function drawText(
  pdf: jsPDF,
  point: Point,
  offsetX: number,
  offsetY: number,
  text: string,
  fontSize: number,
  align: any,
  maxWidth: number
) {
  pdf.setFontSize(fontSize);
  const opt: TextOptionsLight = {
    align,
    maxWidth,
  }
  const { x, y } = point
  pdf.text(text, x + offsetX, y + offsetY, opt);
}


function tryFilePath(val: string): string {
  let newPath = val;
  const dir = path.dirname(val);
  const ext = path.extname(val);
  const base = path.basename(val, ext);
  let i = 1;
  while (fs.existsSync(newPath)) {
    newPath = path.join(dir, `${base}(${i})${ext}`);
    i++;
  }
  return newPath;
}
